package summer.codegenerator.web;

import summer.codegenerator.dto.ListParam;
import summer.codegenerator.dto.OrderModel;
import summer.codegenerator.dto.UniDelModel;
import summer.codegenerator.model.Entity;
import summer.codegenerator.persistence.hibernate.base.tool.Pagination;
import summer.codegenerator.service.EntityService;
import summer.codegenerator.service.base.BaseService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 */
@Controller
@RequestMapping("/uni")
@ResponseBody
public class UniversalController {

	private static final Map<String, UniversalModelServiceClassConfig> configs =
			new HashMap<String, UniversalModelServiceClassConfig>() {
				{
					put("entity", new UniversalModelServiceClassConfig(Entity.class, EntityService.class));
				}
			};

	private BaseService getBaseService(String modelName) throws ClassNotFoundException {
		UniversalModelServiceClassConfig config = configs.get(modelName);
		if (config == null) {
			throw new ClassNotFoundException(modelName);
		}
		return (BaseService) appCtx.getBean(config.getServiceClazz());
	}

	private Class getModelClass(String modelName) throws ClassNotFoundException {
		UniversalModelServiceClassConfig config = configs.get(modelName);
		if (config == null) {
			throw new ClassNotFoundException(modelName);
		}
		return config.getModelClazz();
	}

	@Autowired
	private ApplicationContext appCtx;

	private Object get(String modelName, Long modelId) throws ClassNotFoundException {
		BaseService baseService = this.getBaseService(modelName);
		Object obj = baseService.copyById(modelId);
		return obj;
	}

	private void delete(String modelName, List<Long> modelIds) throws ClassNotFoundException {
		BaseService baseService = this.getBaseService(modelName);
		baseService.delete(modelIds);
	}

	private Object save(String modelName, Object entity) throws Exception {
		Class modelClazz = this.getModelClass(modelName);
		BaseService baseService = this.getBaseService(modelName);

		// 必须！！！
		// 忘了为什么这么做
		String entityString = JSON.toJSONString(entity);
		Object typedEntity = JSON.parseObject(entityString, modelClazz);

		Object obj = baseService.save(typedEntity);
		return obj;
	}

	private Object update(String modelName, Object entity) throws Exception {
		Class modelClazz = this.getModelClass(modelName);
		BaseService baseService = this.getBaseService(modelName);

		String entityString = JSON.toJSONString(entity);
		Object typedEntity = JSON.parseObject(entityString, modelClazz);

		Object obj = baseService.update(typedEntity);
		return obj;
	}

	@RequestMapping(value = "/get/{modelName}/{modelId}")
	public Object urlGet(@PathVariable String modelName, @PathVariable Long modelId) throws ClassNotFoundException {
		return this.get(modelName, modelId);
	}

	@RequestMapping(value = "/get")
	public Object paramGet(@RequestBody Map<String, Object> param) throws ClassNotFoundException {
		String modelName = param.get("modelName").toString();
		Long modelId = Long.parseLong(param.get("modelId").toString());
		return this.get(modelName, modelId);
	}

	@RequestMapping(value = "/delete")
	public void paramDel(@RequestBody UniDelModel param) throws ClassNotFoundException {
		String modelName = param.getModelName();
		List<Long> modelIds = param.getModelIds();
		if (modelIds != null && modelIds.size() > 0) {
			this.delete(modelName, modelIds);
			;
		}
	}

	@RequestMapping(value = "/save")
	public Object paramSave(@RequestBody Map<String, Object> param) throws Exception {
		String modelName = param.get("modelName").toString();
		Object entity = param.get("model");
		return this.save(modelName, entity);
	}

	@RequestMapping(value = "/update")
	public Object paramUpdate(@RequestBody Map<String, Object> param) throws Exception {
		String modelName = param.get("modelName").toString();
		Object entity = param.get("model");
		return this.update(modelName, entity);
	}

	@RequestMapping(value = "/list")
	public Map<String, Object> listByCriteria(@RequestBody ListParam param) throws ClassNotFoundException {

		Pagination pagination = param.getPagination();
		JSONObject condition = (JSONObject) param.getCondition();

		BaseService baseService = this.getBaseService(param.getModelName());

		// 将排序转变成Hibernate识别排序变量
		List<Order> orders = OrderModel.genOrders(param.getOrders());

		// 列表数据
		Map<String, Object> map = new HashMap<String, Object>();
		List data = baseService.listByCriteria(condition, orders, pagination);
		map.put("list", data);
		if (pagination == null) {
			pagination = new Pagination();
		}
		// 分页数据
		pagination.setTotal(baseService.countTotalByCriteria(condition));
		map.put("pagination", pagination);

		return map;
	}
}
